﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace KP_TCP_Client
{
    public class TcpClientMana
    {
        public Socket tcpClient;
        public string numstr;
        public bool flag;
    }

    public class CClient
    {
        /// <summary>
        /// 当前电脑的IP
        /// </summary>
        static public string hostIp = "127.0.0.1";
        /// <summary>
        /// 线程管理
        /// </summary>
        static public Dictionary<string,Thread> _threadMana = new Dictionary<string, Thread>();

        static public object sendlock = new object();

        //static public List<TcpClientMana> _tcMana = new List<TcpClientMana>();
        /// <summary>
        /// DIO索引
        /// </summary>
        static Dictionary<string, int> DIOindex = new Dictionary<string, int>();

        #region 获取当前电脑IP
        /// <summary>
        /// 获取当前电脑IP
        /// </summary>
        static public void GetCurrentComputerIP()
        {
            //获取当前电脑IP
            IPHostEntry hostEntry = Dns.GetHostEntry("");
            foreach (IPAddress address in hostEntry.AddressList)
            {
                if (address.AddressFamily == AddressFamily.InterNetwork)
                {
                    hostIp = address.ToString();
                    break;
                }
            }
        }
        #endregion

        /// <summary>
        /// 连接服务器
        /// </summary>
        static public void LinkServer()
        {
            int threadNum = 1;

            Console.WriteLine("请输入要模拟的设备数量，直接回车即默认为1：");
            string num = Console.ReadLine();
            threadNum = num==""?1: Convert.ToInt32(num);

            Console.WriteLine("请输入服务器的IP地址，如果用121.196.201.131地址直接回车即可：");
            string ip = Console.ReadLine();
            if(ip!="")
            {
                hostIp = ip;
            }
            else
            {
                hostIp = "121.196.201.131";
            }

            Console.WriteLine("将要创建的线程数为:" + (threadNum*2).ToString());
            Console.WriteLine("服务器IP为："+ hostIp);

            for(int i=0;i< threadNum; i++)
            //int i = 1;
            {
                //定义一个套接字监听  
                Socket socketclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                //获取文本框中的IP地址  
                IPAddress address = IPAddress.Parse( hostIp);

                //将获取的IP地址和端口号绑定在网络节点上  
                IPEndPoint point = new IPEndPoint(address, 3306);

                try
                {
                    socketclient.Connect(point);

                    int DIOStatus = 0;
                    DIOindex.Add(socketclient.LocalEndPoint.ToString(), DIOStatus);

                    TcpClientMana tcm = new TcpClientMana();
                    tcm.flag = false;
                    Thread th = new Thread(TCPClientThreadSendNew );
                    tcm.tcpClient = socketclient;
                    tcm.numstr = i.ToString();
                    _threadMana.Add(tcm.numstr, th);
                    th.IsBackground = true;
                    th.Start(tcm);
                    

                    Console.WriteLine("已创建的线程数为：" + (2*i+1).ToString());

                    Thread thr = new Thread(TCPClientThreadNew);
                    thr.IsBackground = true;
                    thr.Start(tcm);
                    Console.WriteLine("已创建的线程数为：" + (2 * (i + 1)).ToString());
                }
                catch {
                    Console.WriteLine("连接失败。。。");
                }

                //Thread.Sleep(100);
            }
        }

        /// <summary>
        /// TCP客户端线程
        /// </summary>
        /// <param name="clientObj"></param>
        /// <param name="numObj"></param>
        static public void TCPClientThread(object clientObj)
        {
            TcpClientMana tcm = clientObj as TcpClientMana;
            Socket tcpClient = tcm.tcpClient;
            string numstr = tcm.numstr;
            byte[] buffer = new byte[256];
            int dataLen = 0;
            uint DOStatus = 0;
            uint DIStatus = 0;

            while (true)
            {
                try
                {
                    dataLen = tcpClient.Receive(buffer);

                    string rATCmd = MyConvert.AsciiByteToString(buffer, dataLen);
                    if (rATCmd != null)
                    {
                        switch(rATCmd)
                        {
                            case "AT+NAME=?\r\n":
                                {
                                    string cmdStr = "+NNAME:Computer" + numstr + "\r\n";
                                    byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                    tcpClient.Send(buf);
                                }
                                
                                break;
                            case "AT+STACH0=?\r\n":
                                {
                                    //int i = 0;
                                    //lock(sendlock)
                                    //{
                                    //    for (i=0;i<16;i++)
                                    //    {
                                    //        if((i%2) == 0)
                                    //        {
                                    //            string cmdStr = "+STACH" + i.ToString() + ":0,100000\r\n";
                                    //            byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                    //            tcpClient.Send(buf);
                                    //        }
                                    //        else
                                    //        {
                                    //            string cmdStr = "+STACH" + i.ToString() + ":1,100000\r\n";
                                    //            byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                    //            tcpClient.Send(buf);
                                    //        }
                                    //    }
                                    //}

                                    DOStatus = (uint)0x00000001 << DIOindex[tcpClient.LocalEndPoint.ToString()];
                                    string cmdStr = "";
                                    lock (sendlock)
                                    {
                                        for (int i = 1; i <= 16; i++)
                                        {
                                            if ((DOStatus & ((uint)0x00000001 << (i - 1))) > 0)
                                            {
                                                cmdStr = "+STACH" + i.ToString() + ":1,100\r\n";
                                            }
                                            else
                                            {
                                                cmdStr = "+STACH" + i.ToString() + ":0,100\r\n";
                                            }
                                            byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                            tcpClient.Send(buf);
                                        }
                                    }
                                }
                                break;
                            case "AT+OCCH0=?\r\n":
                                {
                                    //int i = 0;
                                    //lock (sendlock)
                                    //{
                                    //    for (i = 0; i < 16; i++)
                                    //    {
                                    //        if ((i % 2) == 0)
                                    //        {
                                    //            string cmdStr = "+OCCH" + i.ToString() + ":0\r\n";
                                    //            byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                    //            tcpClient.Send(buf);
                                    //        }
                                    //        else
                                    //        {
                                    //            string cmdStr = "+OCCH" + i.ToString() + ":1\r\n";
                                    //            byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                    //            tcpClient.Send(buf);
                                    //        }
                                    //    }
                                    //}

                                    DIStatus = (uint)0x00008000 >> DIOindex[tcpClient.LocalEndPoint.ToString()];

                                    string cmdStr = "";

                                    lock (sendlock)
                                    {
                                        for (int i = 1; i <= 16; i++)
                                        {
                                            if ((DIStatus & ((uint)0x00000001 << (i - 1))) > 0)
                                            {
                                                cmdStr = "+OCCH" + i.ToString() + ":1\r\n";
                                            }
                                            else
                                            {
                                                cmdStr = "+OCCH" + i.ToString() + ":0\r\n";
                                            }
                                            byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                            tcpClient.Send(buf);
                                        }
                                    }
                                }
                                break;
                            default:
                                break;
                        }
                    }
                }
                catch (Exception e){
                    Console.WriteLine(e.Message);
                    _threadMana.Remove(tcm.numstr);
                    tcm.tcpClient.Close();
                    Thread.CurrentThread.Abort();
                    
                }
            }
        }



        static public void TCPClientThreadSend(object clientObj)
        {
            TcpClientMana tcm = clientObj as TcpClientMana;
            Socket tcpClient = tcm.tcpClient;
            int status = 0;

            while (_threadMana.Keys.Contains(tcm.numstr) == false) ;

            Thread.Sleep(200);

            uint DOStatus = 0;
            uint DIStatus = 0;

            while (true)
            {
                try
                {
                    switch(status)
                    {
                        case 0:
                            {
                                status = 1;
                                DOStatus = (uint)0x00000001 << DIOindex[tcpClient.LocalEndPoint.ToString()];
                                string cmdStr = "";
                                lock (sendlock)
                                {
                                    for (int i=1;i<=16;i++)
                                    {
                                        if((DOStatus & ((uint)0x00000001 << (i-1))) > 0)
                                        {
                                            cmdStr = "+STACH" + i.ToString() + ":1,100\r\n";
                                        }
                                        else
                                        {
                                            cmdStr = "+STACH" + i.ToString() + ":0,100\r\n";
                                        }
                                        byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                        tcpClient.Send(buf);
                                    }
                                }

                            }
                            break;

                        case 1:
                            {
                                status = 0;
                                DIStatus = (uint)0x00008000 >> DIOindex[tcpClient.LocalEndPoint.ToString()];
                                
                                string cmdStr = "";

                                lock (sendlock)
                                {
                                    for (int i = 1; i <= 16; i++)
                                    {
                                        if ((DIStatus & ((uint)0x00000001 << (i - 1))) > 0)
                                        {
                                            cmdStr = "+OCCH" + i.ToString() + ":1\r\n";
                                        }
                                        else
                                        {
                                            cmdStr = "+OCCH" + i.ToString() + ":0\r\n";
                                        }
                                        byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                                        tcpClient.Send(buf);
                                    }
                                }

                                DIOindex[tcpClient.LocalEndPoint.ToString()]++;
                                if (DIOindex[tcpClient.LocalEndPoint.ToString()] >= 16)
                                    DIOindex[tcpClient.LocalEndPoint.ToString()] = 0;

                            }
                            break;

                        default:
                            break;
                    }

                    Thread.Sleep(500);
                }
                catch
                {

                }
            }
        }


        /// <summary>
        /// TCP客户端线程
        /// </summary>
        /// <param name="clientObj"></param>
        /// <param name="numObj"></param>
        static public void TCPClientThreadNew(object clientObj)
        {
            TcpClientMana tcm = clientObj as TcpClientMana;
            Socket tcpClient = tcm.tcpClient;
            string numstr = tcm.numstr;
            byte[] buffer = new byte[256];
            int dataLen = 0;
            //while (_threadMana.Keys.Contains(tcm.numstr) == false) ;
            while (tcm.flag == false) ;
            while (true)
            {
                try
                {
                    dataLen = tcpClient.Receive(buffer);

                    string rATCmd = MyConvert.AsciiByteToString(buffer, dataLen);
                    Console.WriteLine("接收：" + rATCmd);

                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    _threadMana.Remove(tcm.numstr);
                    tcm.tcpClient.Close();
                    Thread.CurrentThread.Abort();

                }
            }
        }

        static public void TCPClientThreadSendNew(object clientObj)
        {
            TcpClientMana tcm = clientObj as TcpClientMana;
            Socket tcpClient = tcm.tcpClient;
            
            string cmdStr = "";

            while (true)
            {
                try
                {
                    cmdStr = "Device Number:" + (tcm.numstr + 1).ToString();
                    byte[] buf = MyConvert.StringToAsciiByte(cmdStr);
                    tcpClient.Send(buf);
                    tcm.flag = true;

                    Thread.Sleep(500);
                }
                catch
                {

                }
            }
        }
    }
}
